﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Windows.Input;
using Foundation;
using Foundation.ExtensionMethods;
using Poet.Views;

namespace Poet.ViewModels
{
    [DataContract]
    public class SaveViewModel : ViewModel
    {
        public SaveViewModel()
        {
            Initialize();
        }

        public bool DialogResult { get; set; }
        public ObservableCollection<DocumentView> Items { get; private set; }
        public ObservableCollection<DocumentView> SelectedItems { get; private set; }

        public void SetItems(ObservableCollection<DocumentView> items, IEnumerable<DocumentView> selectedItems)
        {
            SelectedItems.Clear();
            Items = items ?? new ObservableCollection<DocumentView>();
            SelectedItems.AddRange(selectedItems);
        }

        public bool IsAllItemsSelected
        {
            get { return Items.Where(i => ApplicationCommands.Save.CanExecute(null, i)).All(i => SelectedItems.Contains(i)); }
        }

        [OnDeserialized]
        private void Initialize(StreamingContext context = default(StreamingContext))
        {
            Executed();
            CanExecute();
            SelectedItems = new ObservableCollection<DocumentView>();
            SelectedItems.CollectionChanged += (sender, args) => RaisePropertyChangedEvent(() => IsAllItemsSelected);
            ApplicationClosing += () => this.TrySerializeDataContract();
        }

        private void CanExecute()
        {
            this[ApplicationCommands.Save].CanExecute +=
                (sender, args) => args.CanExecute = SelectedItems.Any(i => ApplicationCommands.Save.CanExecute(null, i));
        }

        private void Executed()
        {
            this[ApplicationCommands.Save].Executed += (sender, args) =>
                {
                    var cancel = new CancelEventArgs();
                    foreach (var item in SelectedItems.Where(item => ApplicationCommands.Save.CanExecute(null, item)))
                    {
                        ApplicationCommands.Save.Execute(cancel, item);
                        if (cancel.Cancel) break;
                    }

                    if (SelectedItems.Any(i => ApplicationCommands.Save.CanExecute(null, i)))
                    {
                        DialogResult = true;
                        return;
                    }

                    DialogResult = true;
                    OnClosing(sender, new CancelEventArgs());
                };

            this[ApplicationCommands.Close].Executed += (sender, args) =>
                {
                    DialogResult = args.Parameter == null;
                    OnClosing(sender, new CancelEventArgs());
                };

            this[ApplicationCommands.SelectAll].Executed += (sender, args) =>
                {
                    var isChecked = (bool) args.Parameter;
                    foreach (var item in Items)
                    {
                        if (!SelectedItems.Contains(item) && isChecked) SelectedItems.Add(item);
                        if (SelectedItems.Contains(item) && !isChecked) SelectedItems.Remove(item);
                    }
                };
        }
    }
}
